#include <iostream>
#include <queue>
const int NUM = 5;

template<class T>
class ThreadPool
{
private:
    bool IsEmpty()
    {
        return _task_queue.size() == 0;
    }

    void LockQueue()
    {
        pthread_mutex_lock(&_mutex);
    }

    void UnLockQueue()
    {
        pthread_mutex_unlock(&_mutex);
    }

    void Wait()
    {
        pthread_cond_wait(&_cond,&_mutex);
    }

    void WakeUp()
    {
        pthread_cond_signal(&_cond);
    }

public:
    ThreadPool(int num = NUM)
        :_thread_num(num)
    {
        pthread_mutex_init(&_mutex,nullptr);
        pthread_cond_init(&_cond,nullptr);
    }

    ~ThreadPool()
    {
        pthread_mutex_destroy(&_mutex);
        pthread_cond_destroy(&_cond);
    }

    //线程池中线程执行历程
    static void* Routine(void* arg)
    {
        pthread_detach(pthread_self());
        ThreadPool* self = (ThreadPool*)arg;
        while(true)
        {
            self->LockQueue();
            while(self->IsEmpty())
            {
                self->Wait();
            }
            T task;
            self->Pop(task);
            self->UnLockQueue();

            //任务处理
            task.Run();
        }
    }

    void ThreadPoolInit()
    {
        pthread_t tid;
        for(int i = 0;i < _thread_num;i++)
        {
            pthread_create(&tid,nullptr,Routine,this);
        }
    }

    //往任务队列里塞任务，主线程调用
    void Push(const T& task)
    {
        LockQueue();
        _task_queue.push(task);
        UnLockQueue();
        WakeUp();
    }
    //从任务队列中获取任务
    void Pop(T& task)
    {
        task = _task_queue.front();
        _task_queue.pop();
    }
private:
    std::queue<T> _task_queue;      //任务队列
    int _thread_num;                //线程数量
    pthread_mutex_t _mutex;         //互斥锁
    pthread_cond_t _cond;           //条件变量
};